package com.aloda.ojquestion.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.aloda.api.client.JudgeClient;
import com.aloda.ojcommon.anno.RateLimit;
import com.aloda.ojcommon.constant.ExceptionConstant;
import com.aloda.ojcommon.constant.QuestionConstant;
import com.aloda.ojcommon.context.UserBaseContext;
import com.aloda.ojcommon.domain.dto.UserCacheDTO;
import com.aloda.ojcommon.domain.entity.JudgeInfo;
import com.aloda.ojcommon.domain.enums.UserRoleEnum;
import com.aloda.ojcommon.domain.result.PageResult;
import com.aloda.ojcommon.exception.ParamsException;
import com.aloda.ojquestion.mapper.QuestionMapper;
import com.aloda.ojquestion.mapper.QuestionSubmitMapper;
import com.aloda.ojquestion.pojo.dto.QuestionSubmitDTO;
import com.aloda.ojquestion.pojo.dto.QuestionSubmitPageDTO;
import com.aloda.ojquestion.pojo.dto.QuestionSubmitUnionDTO;
import com.aloda.ojcommon.domain.entity.Question;
import com.aloda.ojcommon.domain.entity.QuestionSubmit;
import com.aloda.ojcommon.domain.enums.QuestionSubmitLanguageEnum;
import com.aloda.ojcommon.domain.enums.QuestionSubmitStatusEnum;
import com.aloda.ojquestion.pojo.vo.QuestionSubmitPageVO;
import com.aloda.ojquestion.pojo.vo.QuestionSubmitVO;
import com.aloda.ojquestion.service.QuestionSubmitService;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
* @author aloda
* @description 针对表【question_submit(题目提交表)】的数据库操作Service实现
* @createDate 2025-04-25 15:51:38
*/
@Slf4j
@Service
public class QuestionSubmitServiceImpl extends ServiceImpl<QuestionSubmitMapper, QuestionSubmit> implements QuestionSubmitService {

    @Resource
    private QuestionMapper questionMapper;

    @Resource
    private QuestionSubmitMapper questionSubmitMapper;

    @Resource
    private RabbitTemplate rabbitTemplate;

    /**
     * 提交题目
     *
     * @param questionSubmitDTO
     * @return
     */
    @RateLimit(limit = 2, period = 30)
    @Override
    public QuestionSubmitVO submitQuestion(QuestionSubmitDTO questionSubmitDTO) {
        // 1.校验参数
        checkQuestionSubmit(questionSubmitDTO);
        // 2.新增提交记录
        QuestionSubmit questionSubmit = QuestionSubmitDTO.toQuestionSubmit(questionSubmitDTO);
        questionSubmit.setSubmitStatus(QuestionSubmitStatusEnum.WAITING.getValue());
        questionSubmit.setJudgeInfo("{}");
        questionSubmit.setUserId(UserBaseContext.getUser().getId());
        questionSubmit.setCreateTime(LocalDateTime.now());
        questionSubmit.setUpdateTime(LocalDateTime.now());
        questionSubmitMapper.insert(questionSubmit);
        // 新增提交数量
        LambdaUpdateWrapper<Question> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(Question::getId, questionSubmit.getQuestionId())
                .setIncrBy(Question::getSubmitNum, 1);
        questionMapper.update(wrapper);
        // 3.将提交发送异步请求给判题服务进行判题
        try {
            rabbitTemplate.convertAndSend("judge.topic", "judge.task", questionSubmit.getId());
        } catch (Exception e) {
            log.error("发送判题任务失败，题目id:{}， 提交记录id:{}", questionSubmit.getQuestionId(), questionSubmit.getId(), e);
        }
        // 4.返回提交记录的返回对象
        return QuestionSubmitVO.of(questionSubmit);
    }

    /**
     * 校验题目提交信息是否合法
     * @param questionSubmitDTO
     */
    @Override
    public void checkQuestionSubmit(QuestionSubmitDTO questionSubmitDTO) {
        Long questionId = questionSubmitDTO.getQuestionId();
        String code = questionSubmitDTO.getCode();
        String language = questionSubmitDTO.getLanguage();
        if (StrUtil.isEmpty(code) || code.length() > QuestionConstant.QUESTION_SUBMIT_CODE_MAX_LENGTH) {
            throw new ParamsException(ExceptionConstant.QUESTION_CODE_EMPTY_OR_TOO_LONG);
        }
        QuestionSubmitLanguageEnum enumByValue = QuestionSubmitLanguageEnum.getEnumByText(language);
        if (enumByValue == null) {
            throw new ParamsException(ExceptionConstant.INVALID_PROGRAMMING_LANGUAGE);
        }
        Question question = questionMapper.selectById(questionId);
        if (BeanUtil.isEmpty(question)) {
            throw new ParamsException(ExceptionConstant.QUESTION_IS_NOT_EXIST);
        }
    }

    /**
     * 分页查询
     *
     * @param questionSubmitPageDTO
     * @return
     */
    @Override
    public PageResult<QuestionSubmitPageVO> pageQuery(QuestionSubmitPageDTO questionSubmitPageDTO) {
        Page<QuestionSubmitUnionDTO> page = questionSubmitPageDTO.toMpPageDefaultSortByUpdateTimeDesc();
        // 如果用户为管理员，可以查询所有用户答题记录；如果为普通用户，只查询本人答题记录
        UserCacheDTO userCacheDTO = UserBaseContext.getUser();
        if (userCacheDTO.getUserRole().equals(UserRoleEnum.USER.getRole())) {
            questionSubmitPageDTO.setUserId(userCacheDTO.getId());
        }
        questionSubmitMapper.getPage(page ,questionSubmitPageDTO);
        List<QuestionSubmitPageVO> list = page.getRecords().stream().map(questionSubmitUnionDTO -> {
            QuestionSubmitPageVO questionSubmitPageVO =
                    BeanUtil.toBeanIgnoreError(questionSubmitUnionDTO, QuestionSubmitPageVO.class);
            questionSubmitPageVO.setJudgeInfo(JSONUtil.toBean(questionSubmitUnionDTO.getJudgeInfo(), JudgeInfo.class));
            return questionSubmitPageVO;
        }).collect(Collectors.toList());
        return new PageResult<>(page.getTotal(), list);
    }
}




